home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload Trio 2 / Shareware Overload Trio Volume 2 (Chestnut CD-ROM).ISO / dir38 / vgaworm.zip / VGAWORMS.C < prev    next >
C/C++ Source or Header  |  1993-10-13  |  10KB  |  259 lines

  1. /****************************************/
  2. /* VGAWORMS.C                           */
  3. /* (C) Copyright 1993 David Bollinger   */
  4. /* send comments to CIS ID# 72510,3623  */
  5. /* compiled with Borland C++ 3.0        */
  6. /* command line: bcc -ms -v- vgaworms.c */
  7. /****************************************/
  8.  
  9. #include <bios.h>
  10. #include <mem.h>
  11. #include <stdlib.h>
  12. #include <time.h>
  13. #include "vgaworms.h"
  14.  
  15. #define TRUE       (0==0)
  16. #define FALSE      (0==1)
  17. #define AND        &&
  18. #define OR         ||
  19. #define NOT        !
  20. #define MAXX       320     // screen x dimension
  21. #define MAXY       200     // screen y dimension
  22. #define MAXWORMS   16      // how many worms (at least 1)
  23.                            //   mainly limited by CPU speed (and memory)
  24.                            //   practical limit of about 50 on 80486
  25.                            //   due to screen clutter
  26. #define MAXSEGS    90      // how many segments in each worm, (max 90)
  27.                            //   if less than 90 not all colors will be used
  28. #define CHANGEDIR  200     // how frequently should the worm change direction
  29.                            //   lower values cause more frequent changes
  30. #define MAXCUSP    30      // how sharp a turn is allowed (0-359)
  31.                            //   smaller values create smoother turns
  32.  
  33. /********************/
  34. /* global variables */
  35. /********************/
  36. typedef struct
  37.    {
  38.    int x;                  // x screen coordinate of this segment
  39.    int y;                  // y screen coordinate of this segment
  40.    } WORM[MAXSEGS];
  41.  
  42. typedef struct
  43.    {
  44.    int cx;                 // center x screen coordinate of this worm
  45.    int cy;                 // center y screen coordinate of this worm
  46.    int theta;              // current angle of rotation of this worm
  47.    int tinc;               // current rotation direction 1=CCW, -1=CW
  48.    int radius;             // current radius of path
  49.    } DIRECTION;
  50.  
  51. WORM worms[MAXWORMS];
  52. DIRECTION dirs[MAXWORMS];
  53. char notice[] = "VGAWORMS.C (C) 1993 David Bollinger";
  54.  
  55. /***********************/
  56. /* function prototypes */
  57. /***********************/
  58. void InitWorms(void);
  59. void InitWormAt(DIRECTION *thisdir, int x, int y);
  60. void UpdateWorms(void);
  61. void DrawWorms(void);
  62. void SetVideoMode(int mode);
  63. void PutPixel(int x, int y, int c);
  64. void SetupPalette(void);
  65.  
  66. /***************************************************************************/
  67. main()
  68.    {
  69.    SetVideoMode(19);       // 320x200 256 color VGA graphics mode
  70.    SetupPalette();         // make a rainbow palette
  71.    randomize();
  72.  
  73.    InitWorms();             // set up starting positions
  74.  
  75.    while(bioskey(1))       // chew up any keys waiting in buffer
  76.       bioskey(0);
  77.  
  78.    while(NOT bioskey(1))   // do until user presses a key
  79.       {
  80.       DrawWorms();
  81.       UpdateWorms();
  82.       }
  83.  
  84.    bioskey(0);             // chew up that key
  85.    SetVideoMode(3);        // return to 80x25 text mode
  86.    return 0;
  87.    }
  88.  
  89. /***************************************************************************/
  90. void InitWorms(void)
  91.    {
  92.    register int worm, seg, x, y;
  93.    WORM *thisworm = &worms[0];
  94.    DIRECTION *thisdir = &dirs[0];
  95.  
  96.    for (worm=MAXWORMS-1; worm>=0; worm--, thisworm++, thisdir++)
  97.       {
  98.       /********************************************/
  99.       /* pick any point on the screen to start at */
  100.       /********************************************/
  101.       x = random(MAXX);
  102.       y = random(MAXY);
  103.  
  104.       /*******************************************/
  105.       /* set each segment to same x,y coordinate */
  106.       /*******************************************/
  107.       for (seg=MAXSEGS-1; seg>=0; seg--)
  108.          {
  109.          (*thisworm)[seg].x = x;
  110.          (*thisworm)[seg].y = y;
  111.          }
  112.  
  113.       /*********************************************************************/
  114.       /* set theta and tinc to default values, InitWormAt will change them */
  115.       /*********************************************************************/
  116.       thisdir->theta = 0;
  117.       thisdir->tinc = 1;
  118.       InitWormAt(thisdir, x, y);
  119.       }
  120.    }
  121.  
  122. /***************************************************************************/
  123. void InitWormAt(DIRECTION *thisdir, int x, int y)
  124.    {
  125.    int inc;
  126.  
  127.    /********************************************************************/
  128.    /* pick a new radius at random, the size limit 10-50 is a practical */
  129.    /* limit based on the resolution of the trig tables and screen.     */
  130.    /* More than 50 causes holes to appear in the worms, while values   */
  131.    /* less than 10 cause the worm to scrunch up into a little ball     */
  132.    /********************************************************************/
  133.    thisdir->radius = random(40)+10;
  134.  
  135.    /********************************************************************/
  136.    /* pick a new angle, use the complementary angle (Θ+180) and add in */
  137.    /* and extra 360 to make sure that the result is positive, then add */
  138.    /* in a random amount - the larger this random amount the "sharper" */
  139.    /* the turn will be.  Finally change the rotation direction.        */
  140.    /********************************************************************/
  141.    inc = random(MAXCUSP)-(MAXCUSP/2);
  142.    thisdir->theta  = (thisdir->theta + 540 + inc) % 360;
  143.    thisdir->tinc   = -thisdir->tinc;
  144.  
  145.    /***********************************/
  146.    /* figure out the new center point */
  147.    /***********************************/
  148.    thisdir->cx  = ((x - (thisdir->radius * sintable[thisdir->theta])/128) + MAXX) % MAXX;
  149.    thisdir->cy  = ((y - (thisdir->radius * costable[thisdir->theta])/128) + MAXY) % MAXY;
  150.    }
  151.  
  152. /***************************************************************************/
  153. /* moves each segment of all worms to a new position */
  154. /*****************************************************/
  155. void UpdateWorms(void)
  156.    {
  157.    register int worm;
  158.    WORM *thisworm = &worms[0];
  159.    DIRECTION *thisdir = &dirs[0];
  160.  
  161.    for(worm=MAXWORMS-1; worm>=0; worm--, thisworm++, thisdir++)
  162.       {
  163.       /*********************************************/
  164.       /* is it time for a random direction change? */
  165.       /*********************************************/
  166.       if (random(CHANGEDIR)==0)
  167.          InitWormAt(thisdir, (*thisworm)[0].x, (*thisworm)[0].y);
  168.  
  169.       /*****************************************************/
  170.       /* each ball (except first) moves forward 1 position */
  171.       /*****************************************************/
  172.       memmove((void *)(&(*thisworm)[1].x), (void *)(&(*thisworm)[0].x), sizeof(WORM)-4);
  173.  
  174.       /**********************************************/
  175.       /* now find a new position for the first ball */
  176.       /**********************************************/
  177.       (*thisworm)[0].x = ((thisdir->cx + ((thisdir->radius * sintable[thisdir->theta])>>7)) + MAXX) % MAXX;
  178.       (*thisworm)[0].y = ((thisdir->cy + ((thisdir->radius * costable[thisdir->theta])>>7)) + MAXY) % MAXY;
  179.  
  180.       /*****************************************/
  181.       /* move to the next position on the path */
  182.       /*****************************************/
  183.       thisdir->theta = (thisdir->theta + thisdir->tinc + 360) % 360;
  184.       }
  185.    }
  186.  
  187. /***************************************************************************/
  188. /* draw each ball of each set - last ball draws in color 0 to erase tail */
  189. /*************************************************************************/
  190. void DrawWorms(void)
  191.    {
  192.    register int seg, worm;
  193.    WORM *thisworm = &worms[0];
  194.  
  195.    for (worm=MAXWORMS-1; worm>=0; worm--, thisworm++)
  196.       for (seg=MAXSEGS-1; seg>=0; seg--)
  197.          PutPixel((*thisworm)[seg].x, (*thisworm)[seg].y, MAXSEGS-1-seg);
  198.    }
  199.  
  200. /***************************************************************************/
  201. /* BIOS call to set video mode */
  202. /*******************************/
  203. void SetVideoMode(int mode)
  204.    {
  205.    asm   mov   ah, 0
  206.    asm   mov   al, byte ptr mode
  207.    asm   int   10h
  208.    }
  209.  
  210. /***************************************************************************/
  211. /* direct video access to screen to plot a single pixel */
  212. /* destroys ax, bx, es                                  */
  213. /********************************************************/
  214. void PutPixel(int x, int y, int c)
  215.    {
  216.    asm   mov   ax, 0xa000
  217.    asm   mov   es, ax
  218.    asm   mov   bx, word ptr y
  219.    asm   shl   bx, 1
  220.    asm   mov   ax, word ptr ytable[bx]
  221.    asm   add   ax, word ptr x
  222.    asm   mov   bx, ax
  223.    asm   mov   ax, word ptr c
  224.    asm   mov   byte ptr es:[bx], al
  225.    }
  226.  
  227. /***************************************************************************/
  228. /* make a nice smooth rainbow palette */
  229. /* destroys ax, bx, cx, dx, es        */
  230. /**************************************/
  231. void SetupPalette(void)
  232.    {
  233.    asm   mov   ax, SEG palette       // get segment of palette
  234.    asm   mov   es, ax
  235.    asm   mov   dx, OFFSET palette    // get offset of palette
  236.    asm   mov   bx, 0                 // start with color # 0
  237.    asm   mov   cx, 90                // load 90 colors
  238.    asm   mov   ax, 0x1012            // bios function 10 subfunction 12
  239.    asm   int   0x10                  // call bios to load palette
  240.    }
  241.  
  242. /***************************************************************************/
  243. /***************************************************************************
  244.   Trig review:       .....
  245.                   ...     ...
  246.                  .           .o  (x, y)
  247.                 .        r  / |.
  248.                .          /   | .
  249.                         / Θ  ┌|  .
  250.              (cx, cy)  o-------  .
  251.                                  .
  252.              x = cx + rsinΘ   ==>   cx = x - rsinΘ
  253.              y = cy + rcosΘ   ==>   cy = y - rcosΘ
  254.  
  255.  ***************************************************************************/
  256. /* end of vgaworms.c */
  257.  
  258.  
  259.